package cn.wolfcode.wolf2w.business.service.impl;

import cn.wolfcode.wolf2w.business.api.RemoteDestinationService;
import cn.wolfcode.wolf2w.business.api.domain.*;
import cn.wolfcode.wolf2w.business.mapper.*;
import cn.wolfcode.wolf2w.business.query.StrategyQuery;
import cn.wolfcode.wolf2w.business.service.IStrategyService;
import cn.wolfcode.wolf2w.business.util.DateUtil;
import cn.wolfcode.wolf2w.business.vo.ThemeVO;
import cn.wolfcode.wolf2w.common.core.constant.SecurityConstants;
import cn.wolfcode.wolf2w.common.core.context.SecurityContextHolder;
import cn.wolfcode.wolf2w.common.redis.service.RedisService;
import cn.wolfcode.wolf2w.common.redis.util.RedisKeys;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 攻略Service业务层处理
 * 
 * @author LSY
 * @date 2025-09-16
 */
@Service
@Transactional
public class StrategyServiceImpl extends ServiceImpl<StrategyMapper,Strategy> implements IStrategyService {

    @Autowired
    private StrategyRankMapper strategyRankMapper;
    @Autowired
    private StrategyConditionMapper strategyConditionMapper;
    @Autowired
    private StrategyCatalogMapper strategyCatalogMapper;
    @Autowired
    private StrategyThemeMapper strategyThemeMapper;
    @Autowired
    private RemoteDestinationService remoteDestinationService;
    @Autowired
    private StrategyContentMapper strategyContentMapper;
    @Autowired
    private RedisService redisService;




//    @Override
//    public IPage<Strategy> queryPageAdmin(StrategyQuery qo) {
//        IPage<Strategy> page = new Page<>(qo.getCurrentPage(), qo.getPageSize());
//        return lambdaQuery()
//                .page(page);
//    }


    @Override
    public IPage<Strategy> queryPage(StrategyQuery qo) {
        IPage<Strategy> page=new Page<>(qo.getCurrentPage(), qo.getPageSize());
        //type ==3  主题
        QueryWrapper<Strategy> wrapper = new QueryWrapper<>();
        if (qo.getType()!=null){
            if(qo.getType()==3){
                wrapper.eq("theme_id", qo.getRefid());
            }else {
                wrapper.eq("dest_id", qo.getRefid());
            }
        }
        wrapper.orderByDesc(qo.getOrderBy());
        page=baseMapper.selectPage(page, wrapper);
        return page;
    }

    @Override
    public List<Strategy> queryViewnnumTop3(Long destId) {
        int limit = destId == null ? 5 : 3;
        //判断destID不为空执行
        return lambdaQuery().eq(destId!=null,Strategy::getDestId,destId)
                .orderByDesc(Strategy::getViewnum)
                .last("limit "+limit).list();
    }

    @Override
    public void statisRank() {
        List<Strategy> abroadList = lambdaQuery().eq(Strategy::getIsabroad, 1)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();

        List<Strategy> chinaList = lambdaQuery().eq(Strategy::getIsabroad, 0)
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();

        List<Strategy> hotList = lambdaQuery()
                .orderByDesc(Strategy::getViewnum)
                .last("limit 10")
                .list();

        Date now = new Date();

        addRank(abroadList, now, 1);
        addRank(chinaList, now, 2);
        addRank(hotList, now, 3);
    }

    @Override
    public List<ThemeVO> queryTheme() {
        QueryWrapper<Strategy> wrapper=new QueryWrapper<>();
        wrapper.groupBy("theme_name");
        wrapper.select("theme_name, GROUP_CONCAT(DISTINCT dest_id) ids, GROUP_CONCAT(DISTINCT dest_name) names");
        List<Map<String, Object>> list = baseMapper.selectMaps(wrapper);
        List<ThemeVO> themeVOList=new ArrayList<>();
        for (Map<String, Object> map : list) {
            String themeName = map.get("theme_name").toString();
            String ids = map.get("ids").toString();
            String names = map.get("names").toString();
            String[] idsArr = ids.split(",");
            String[] namesArr = names.split(",");
            List<Destination> dests=new ArrayList<>();
            for (int i=0;i<idsArr.length;i++){
                Long id = Long.valueOf(idsArr[i]);
                String name = namesArr[i];
                Destination destination = new Destination();
                destination.setId(id);
                destination.setName(name);
                dests.add(destination);
            }
            ThemeVO themeVO = new ThemeVO(themeName, dests);
            themeVOList.add(themeVO);
        }
        return themeVOList;
    }

    @Override
    public void statisCondition() {
        //外国的 type=1 abroad=1
        //可以使用相同的wapper但需要将wapper的字段清空 wapper.clear();
        QueryWrapper<Strategy> abroadWrapper=new QueryWrapper<>();
        abroadWrapper.select("dest_id refid,dest_name name,count(dest_name) count");
        abroadWrapper.eq("isabroad",1);
        abroadWrapper.groupBy("dest_id,dest_name");
        abroadWrapper.orderByDesc("count");
        List<Map<String, Object>> abroadMap = baseMapper.selectMaps(abroadWrapper);
        //国内的 type=2 abroad=0
        QueryWrapper<Strategy> inWrapper=new QueryWrapper<>();
        inWrapper.select("dest_id refid,dest_name name,count(dest_name) count");
        inWrapper.eq("isabroad",0);
        inWrapper.groupBy("dest_id,dest_name");
        inWrapper.orderByDesc("count");
        List<Map<String, Object>> inMap = baseMapper.selectMaps(inWrapper);

        //主题的 type=3
        QueryWrapper<Strategy> themeWrapper=new QueryWrapper<>();
        themeWrapper.select("theme_id refid,theme_name name,count(theme_name) count");
        themeWrapper.groupBy("theme_id,theme_name");
        themeWrapper.orderByDesc("count");
        List<Map<String, Object>> themeMap = baseMapper.selectMaps(themeWrapper);

        Date now = new Date();
        addCondition(abroadMap,now,1);
        addCondition(inMap,now,2);
        addCondition(themeMap,now,3);
    }

    @Override
    public void insert(Strategy strategy) {
        StrategyTheme strategyTheme = strategyThemeMapper.selectById(strategy.getThemeId());
        strategy.setThemeName(strategyTheme.getName());
        StrategyCatalog strategyCatalog = strategyCatalogMapper.selectById(strategy.getCatalogId());
        strategy.setCatalogName(strategyCatalog.getName());
        strategy.setDestId(strategyCatalog.getDestId());
        strategy.setDestName(strategyCatalog.getDestName());
        strategy.setCreateTime(new Date());
        strategy.setViewnum(0L);
        strategy.setReplynum(0L);
        strategy.setFavornum(0L);
        strategy.setSharenum(0L);
        strategy.setThumbsupnum(0L);
        Boolean data = remoteDestinationService.isabroad(strategy.getDestId(), SecurityConstants.INNER).getData();
        strategy.setIsabroad(data?1L:0L);
        baseMapper.insert(strategy);
        Long strategyId = strategy.getId();
        strategy.getContent().setId(strategyId);
        strategyContentMapper.insert(strategy.getContent());
    }

    @Override
    public Map<String, Object> viewnumIncrease(Long sid) {
        String key = strategyKeyHsahInit(sid);
        redisService.incrementCacheMapValue(key,"viewnum",1);
        return redisService.getCacheMap(key);
    }

    @Override
    public Map<String, Object> replynumIncrease(Long sid) {
        String key = strategyKeyHsahInit(sid);
        redisService.incrementCacheMapValue(key,"replynum",1);
        return redisService.getCacheMap(key);
    }

    @Override
    public Map<String, Object> favor(Long sid) {
        Long userId = SecurityContextHolder.getUserId();
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(userId.toString());
        if(!redisService.hasKey(key)){ // 如果用户没有收藏，且redis没有对应的key
            Set<Long> sids=new HashSet<>();
            //空集合redis会自动清掉数据
            sids.add(-1L);
            redisService.setCacheSet(key,sids);
        }
        boolean b=false;
        String hashkey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        if(redisService.isCacheSetContains(key,sid)){
            //取消收藏
            redisService.incrementCacheMapValue(hashkey,"favornum",-1);
            redisService.deleteCacheSetValue(key,sid);
        }else{
            redisService.incrementCacheMapValue(hashkey,"favornum",1);
            redisService.addCacheSetValue(key,sid);
            b=true;
        }
        Map<String, Object> cacheMap = redisService.getCacheMap(hashkey);
        cacheMap.put("result",b);
        return cacheMap;
    }

    @Override
    public Boolean isUserFavor(Long sid, Long uid) {
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid.toString());
        if(!redisService.hasKey(key)){ // 如果用户没有收藏，且redis没有对应的key
            Set<Long> sids=new HashSet<>();
            //空集合redis会自动清掉数据
            sids.add(-1L);
            redisService.setCacheSet(key,sids);
        }
        //判断用户是否收藏了该攻略
        return redisService.isCacheSetContains(key,sid);
    }

    @Override
    public void strategyStatisHashPersistence() {
        String hashkey = RedisKeys.STRATEGY_STATIS_HASH.join("*");
        Collection<String> keys = redisService.keys(hashkey);
        if (keys!=null&& !keys.isEmpty()){
            for (String key : keys) {
                Map<String, Object> cacheMap = redisService.getCacheMap(key);
                lambdaUpdate().eq(Strategy::getId,cacheMap.get("id"))
                        .set(Strategy::getViewnum,cacheMap.get("viewnum"))
                        .set(Strategy::getReplynum,cacheMap.get("replynum"))
                        .set(Strategy::getSharenum,cacheMap.get("sharenum"))
                        .set(Strategy::getFavornum,cacheMap.get("favornum"))
                        .set(Strategy::getThumbsupnum,cacheMap.get("thumbsupnum"))
                        .update();
            }
        }
    }

    /**
     * 只根据uid作为key进行缓存
     * 攻略点赞
     * @param sid
     * @return
     */
//    @Override
//    public Map<String, Object> thumbsup(Long sid) {
//        Date now = new Date();
//        //当天的最后一秒
//        Date endDate = DateUtil.getEndDate(now);
//        //相差时间
//        Long dateBetween = DateUtil.getDateBetween(now, endDate);
//        //userId
//        Long userId = SecurityContextHolder.getUserId();
//        //根据userId创建key
//        String key = RedisKeys.USER_STRATEGY_THUMBSUP.join(userId.toString());
//        //获取hashkey
//        String hashkey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
//        //判断key是否存在:不存在则创建
//        if(!redisService.hasKey(key)){
//            Map<String, Object> map=new HashMap<>();
//            map.put(sid.toString(),0);
//            redisService.setCacheMap(key,map);
//            redisService.expire(key,dateBetween);
//        }
//        //判断sid不存在
//        Map<String, Object> map = redisService.getCacheMap(key);
//        if (map.get(sid.toString())==null){
//            map.put(sid.toString(),0);
//            redisService.setCacheMap(key,map);
//        }
//        //sid存在
//        redisService.incrementCacheMapValue(key,sid.toString(),1);
//        boolean result=false;
//        //取出数据
//        Map<String, Object> cacheMap = redisService.getCacheMap(key);
//        Long num = Long.valueOf(cacheMap.get(sid.toString()).toString());
//        //hashkey
//        Map<String, Object> hashmap = redisService.getCacheMap(hashkey);
//        if (num<=3){
//            redisService.incrementCacheMapValue(hashkey,"thumbsupnum",1);
//            result=true;
//        }
//        hashmap.put("result",result);
//        return hashmap;
//    }

    /**
     * 根据 sid和uid共同作为key来进行redis缓存
     * @param sid
     * @return
     */
    @Override
    public Map<String, Object> thumbsup(Long sid) {
        //注入uid
        Long uid = SecurityContextHolder.getUserId();
        //拼key
        String key = RedisKeys.USER_STRATEGY_THUMBSUP.join(sid.toString(), uid.toString());

        //计算过期时间
        Date now = new Date();
        Date end = DateUtil.getEndDate(now);
        long seconds = DateUtil.getDateBetween(now, end);

        //判断redis中是否有key， 如果没有创建key设置值0
        if( ! redisService.hasKey(key)){
            redisService.setCacheObject(key, 0, seconds, TimeUnit.SECONDS);
        }

        //点赞次数++
        Long ret = redisService.incrementCacheObjectValue(key, 1);

        String hashKey = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());

        //判断点赞次数，如果大于3，设置result为false
        boolean result = false;
        //如果小于等于3，设置result为true
        if(ret <= 3){
            result = true;
            redisService.incrementCacheMapValue(hashKey, "thumbsupnum", 1);
        }
        //查询统计数字map结构，并将result加入到map中

        Map<String, Object> cacheMap = redisService.getCacheMap(hashKey);
        cacheMap.put("result", result);
        //返回map
        return cacheMap;

    }

    private String strategyKeyHsahInit(Long sid) {
        String key = RedisKeys.STRATEGY_STATIS_HASH.join(sid.toString());
        //判断布隆过滤器后进行查询
        //不加会产生穿透
        if(!redisService.hasKey(key)){
            Strategy strategy = this.getById(sid);
            Map<String, Object> map = new HashMap<>();
            map.put("viewnum", Integer.valueOf(strategy.getViewnum().toString()));
            map.put("replynum", Integer.valueOf(strategy.getReplynum().toString()));
            map.put("sharenum", Integer.valueOf(strategy.getSharenum().toString()));
            map.put("favornum", Integer.valueOf(strategy.getFavornum().toString()));
            map.put("thumbsupnum", Integer.valueOf(strategy.getThumbsupnum().toString()));
            map.put("id", strategy.getId());
            redisService.setCacheMap(key,map);
        }
        return key;
    }


    private void addRank(List<Strategy> list,  Date now, long type){
        for (Strategy strategy : list) {
            StrategyRank rank = new StrategyRank();
            rank.setStrategyId(strategy.getId());
            rank.setStrategyTitle(strategy.getTitle());
            rank.setDestName(strategy.getDestName());
            rank.setDestId(strategy.getDestId());
            rank.setStatisnum(strategy.getViewnum());
            rank.setStatisTime(now);
            rank.setType(type);
            strategyRankMapper.insert(rank);
        }
    }
    private void addCondition(List<Map<String, Object>> list,  Date now, long type){
        for (Map<String, Object> map : list) {
            //需要根据type判断是地址还是主题
                StrategyCondition condition = new StrategyCondition();
                //名字
                String name = map.get("name").toString();
                condition.setName(name);
                //数量
                Long count = Long.valueOf(map.get("count").toString());
                condition.setCount(count);
                //关联id
                Long refid = Long.valueOf(map.get("refid").toString());
                condition.setRefid(refid);
                //类型
                condition.setType(type);
                //时间
                condition.setStatisTime(now);
                strategyConditionMapper.insert(condition);
        }
    }
}
